/**
 * @author harae Feng 
 * @date 2019-09-18 16:50:10 
 * @Last Modified by: harae Feng
 * @Last Modified time: 2019-12-23 17:08:08
 * @Describe fetch 工具类
 */

 const fetch = require('node-fetch')
 const request = require('request')
 const fs = require('fs')
 const fileUtil = require('./fileUtil')


/**
 * 加入timeout : 20 s
 * @param options
 * @return {Promise<void>}
 */
 async function fetchV1(url, options={}, isReFirst=true) {
    const start = new Date()
    let data = await Promise.race([fetch(url, options), _timer(20*1000)])
    const ms = new Date() - start
    console.log(`--[fetch]--${!isReFirst?'第2次尝试--':''}${url} ${JSON.stringify(options)} - ${ms}ms`)
    if(data === 'timeout' && isReFirst){ return await fetchV1(url, options, false)}
    return data
 }

function _timer(t){
    return new Promise(resolve=>setTimeout(resolve, t))
        .then(function(res) {
            return 'timeout'
        });
}

 /**
  * request 异步化
  * @param {Object} option 参数
  */
 async function requestPromise(option){
     return new Promise((resolve, reject)=>{
        request({url:option}, (err, body, res)=>{
            resolve(JSON.parse(res))
        }) 
     })
 }

 /**
  * 下载
  * code: 0:成功；1:失败; 2:文件存在
  * @param {String} url 下载链接
  * @param {String} file 绝对路径
  * @param {Boolean} isShowLoading 是否需要下载进度展示(默认:true)
  * @param {Function} callback 各个阶段回调{exist: function, error: function, response: function, data: function, end: function}
  */
 async function requestDown(options, file, isShowLoading=false, callback={}){
    try {
        let url = ``
        if(typeof options === 'string') {url = options}
        else if(typeof options === 'object') {url = options.url}

        console.log(`--[down]--downRequest--请求内容成功，准备写入下载文件：${url}`)
        return new Promise((resolve,reject)=>{
            const start = new Date()
            // 检测文件
            if(fileUtil.existSync(file)){
                console.log(`--[down]--downRequest--文件已存在：${file}`)
                callback.exist && callback.exist()
                resolve({code: 2 , message: 'exist', path: file})
                return
            }

            // 下载逻辑
            let total = 0, body = '', rate = 0, a = 0, stout = null, ing = false
            if(isShowLoading){
                // 下载定时输出
                stout = setInterval(()=>{
                    a !== rate && console.log(`下载rate ${file}: -------  ${rate}% ${total} ${body.length} ${ing}` )
                    a = rate
                }, 3000)

                setTimeout(()=>{
                    clearInterval(stout)
                }, 3 *60*1000)
            }

            let option = {url: url, timeout: 20000}
            option = Object.assign(option, options)
            request(option)
                .on('error', function (err) {
                    if(isShowLoading){
                        stout && clearInterval(stout)
                    }
                    console.warn(`--[down]--downRequest--下载错误： ${url} ${err}`)
                    callback.error && callback.error(file)
                    resolve({code: 1 , message: 'error2', path: file, downloadState: 1})
                    return
                })
                .on('response', function(response) {
                    if(isShowLoading){
                        let len = parseInt(response.headers['content-length'], 10)
                        total = len
                    }
                    callback.response && callback.response()
                })
                .on('data', function (chunk) {
                    if(isShowLoading){
                        body+=chunk
                        try{
                            let allen = body.length
                            rate = total ? (allen / total * 100).toFixed(0) : 0
                        }catch (e) {
                            console.warn('test',e)
                        }

                    }
                    ing = true; // 正在下载？
                    (!ing && callback.data) && callback.data(ing, rate, body, total)
                })
                .on('end', function () {
                    if(isShowLoading) {
                        stout && clearInterval(stout)
                        console.log(`下载rate ${file}: -------  100%`)
                    }
                    const ms = new Date() - start
                    console.log(`--[down]--downRequest--下载成功：${file} - ${ms}ms`)
                    callback.end && callback.end(file)
                    body = null
                    resolve({code: 0 , message: 'ok', path: file, downloadState: 0})
                    return
                })
                .pipe(fs.createWriteStream(file))
        })
    } catch (error) {
        console.log(`--[down]--downRequest--请求下载错误：${error}`)
        callback.error && callback.error(file)
        stout && clearInterval(stout)
        fs.unlinkSync(file)
        return Promise.resolve({code: 1 , message: 'error', path: file, downloadState: 1})
    }

 }

 /**
  *随机机型
  *
  * @param {String} type 类型 ('mobile|brower')
  */
 function randomUa(type){
    const mobileUA = [

    ]
    const BrowerUA = [
        `Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36` // 2019-12-23 google brower
    ]
    if(type === 'mobile'){
        return mobileUA[Math.floor(Math.random()*mobileUA.length)]
    }

    if(type === 'brower'){
        return BrowerUA[Math.floor(Math.random()*BrowerUA.length)]
    }

    const list = [...mobileUA, ...BrowerUA]
    return list[Math.floor(Math.random()*list.length)]
 }

 module.exports = {
    fetchRequest: fetchV1,
    requestDown: requestDown,
    randomUa: randomUa,
 }